package brokerServer

import (
	"broker/interface/iserver"
	"broker/struct/common"
	"broker/struct/connection"
	"broker/struct/model"
	"broker/struct/router"
	"broker/utils"
	"broker/utils/logger"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"net/http"
)

/**
 * @Description
 * @Author huan.wang
 * @Date 2021/5/8 12:02 下午
 **/

var upGrader = websocket.Upgrader{CheckOrigin:func(r *http.Request)bool{
	return true
}}
type WebSocketServer struct {
	//服务器名称
	Name string
	//服务器绑定的ip版本
	IPVersion string
	//服务器监听的ip
	IP string
	//服务器监听端口
	Port string

	//路由表
	routers iserver.IRouterTable

	//服务器路由及消息队列管理
	MsgHandle iserver.IMsgHandle
	//连接管理器
	ConnManager iserver.IConnManager

	//订阅主题管理器
	TopicManager iserver.ITopicManager

	/*连接的hook方法*/
	OnConnStart func(connection iserver.IConnection)
	OnConnStop  func(connection iserver.IConnection)
	OnPublish func(connection iserver.IConnection,message model.PublishMessage)
}

func (ws *WebSocketServer) Start() {

	logger.Info.Printf("[WebSocketServer] %s Version %s Listenner at IP :%s,net IP:%s, Port %s,is starting\n", ws.Name, utils.GetConfig().Version, ws.IP, utils.GetIntranetIp(), ws.Port)
	server := gin.Default()
	server.Any("/mqtt", func(context *gin.Context) {
		logger.Info.Println("收到MQTT消息")
		responseHeader := http.Header{}
		responseHeader.Set("Sec-WebSocket-Protocol","mqtt")
				conn, err := upGrader.Upgrade(context.Writer, context.Request, responseHeader)
				if err != nil {
					logger.Error.Println("[Server] Accept err", err)
				}

				//设置最大连接数的判断
				if ws.ConnManager.GetLen() >= utils.GetConfig().MaxConn {
					//TODO 传给客户端一个超出最大连接数的错误包
					logger.Error.Println("[Server] Maximum number of connections exceeded")
					conn.Close()
				}

				common.ConnIDLock.Lock()
				dealConn := connection.NewWebSocketConnection(ws, conn, common.ConnID, ws.MsgHandle)
				common.ConnID++
				common.ConnIDLock.Unlock()
				go dealConn.Start()
	})
	go server.Run(":" + ws.Port)


}

// Stop 关闭服务器
func (ws *WebSocketServer) Stop() {

	//TODO 将服务器的资源，状态，已开辟的连接信息消除
	//清除所有连接
	ws.ConnManager.ClearAll()
}

func (ws *WebSocketServer) Serve() {
	ws.Start()

	// TODO 做一些启动服务器之后的额外业务
	//阻塞状态
	select {}
}

func (ws *WebSocketServer) GetRouters() iserver.IRouterTable {
	return ws.routers
}

func (ws *WebSocketServer) GetConnManager() iserver.IConnManager {
	return ws.ConnManager
}
func (ws *WebSocketServer) GetTopicManager() iserver.ITopicManager {
	return ws.TopicManager
}

func NewWebSocketServer() iserver.IServer {
	s := &WebSocketServer{
		Name:         utils.GetConfig().Name,
		IPVersion:    utils.GetConfig().IPVersion,
		IP:           utils.GetConfig().Host,
		Port:         utils.GetConfig().WebSocketPort,
		routers:      router.NewRouterTable(),
		MsgHandle:    connection.NewMsgHandle(),
		ConnManager:  connection.NewConnManager(),
		TopicManager: connection.NewTopicManager(),
	}
	return s
}

// SetOnConnStart /*连接Hook*/
//注册连接启动Hook方法
func (ws *WebSocketServer) SetOnConnStart(onConnStart func(connection iserver.IConnection)) {
	ws.OnConnStart = onConnStart
}

// SetOnConnStop 注册连接关闭的Hook方法
func (ws *WebSocketServer) SetOnConnStop(onConnStop func(connection iserver.IConnection)) {
	ws.OnConnStop = onConnStop
}

// SetOnPublish 注册连接关闭的Hook方法
func (ws *WebSocketServer) SetOnPublish(onPublish func(connection iserver.IConnection,message model.PublishMessage)) {
	ws.OnPublish = onPublish
}

// CallOnConnStart 调用连接启动的Hook方法
func (ws *WebSocketServer) CallOnConnStart(connection iserver.IConnection) {
	if ws.OnConnStart != nil {
		ws.OnConnStart(connection)
	}

}

// CallOnConnStop 调用连接关闭的Hook方法
func (ws *WebSocketServer) CallOnConnStop(connection iserver.IConnection) {
	if ws.OnConnStop != nil {
		ws.OnConnStop(connection)
	}
}
// CallOnPublish 调用连接关闭的Hook方法
func (ws *WebSocketServer) CallOnPublish(connection iserver.IConnection,message model.PublishMessage) {
	if ws.OnPublish != nil {
		ws.OnPublish(connection,message)
	}
}
